/*
JavaScript ES6的Set类有以下常见方法：

-  add(value) ：向Set中添加一个值
-  clear() ：删除Set中的所有值
-  delete(value) ：从Set中删除一个值
-  entries() ：返回Set中所有元素的键/值对
-  forEach(callbackFn, thisArg) ：以插入顺序执行给定的回调函数
-  has(value) ：如果Set中存在给定的值则返回 true ，否则返回 false
-  keys() ：返回Set中所有元素的键
-  size ：返回Set中元素的数量
-  values() ：返回Set中所有元素的值

除此之外，Set类还提供了 Symbol.iterator 属性，可以用于使用 for...of 循环遍历Set中的元素。
 */

class mySet {
    constructor(iterator = []) {
        //? Symbol.iterator  是一个内置的 Symbol 类型常量，它定义了一个默认的迭代器函数。当一个对象实现了  Symbol.iterator  方法时，该对象就是可迭代的
        if (typeof iterator[Symbol.iterator] !== "function") {
            throw new TypeError(`你提供的${iterator}不是一个可迭代的对象`)
        }
        this.list = {}
        this.size = iterator.length
        //? 初始数据读入
        iterator.forEach(val => {
            this.list[val] = val
        })
    }
    //? 先判断里面有没有 没有才能加
    add(val) {
        if (!this.list[val]) {
            this.list[val] = val
            this.size++
            return true
        }
        return false
    }
    //? 是否有某个元素
    has(val) {
        //? 判断下是否是对象，如果是对象返回false
        if (val !== null && typeof val === 'object') return false
        //? hasOwnProperty() 方法会返回一个布尔值，指示对象自身属性中是否具有指定的属性（也就是，是否有指定的键）
        return this.list.hasOwnProperty(val)
    }
    //? 删除元素
    delete(val) {
        if (this.list[val]) {
            //? delete 运算符用于删除对象的一个属性；如果该属性的值是一个对象，并且没有更多对该对象的引用，该属性所持有的对象最终会自动释放
            delete this.list[val]
            this.size--
            return true
        }
        return false
    }
    //? 清空
    clear() {
        this.list = {}
        this.size = 0
    }
    //? 获取所有键
    keys() {
        // 键和值是相等的，以值为主
        return Object.values(this.list)
    }
    //? 获取所有值
    values() {
        //? 键和值是相等的，以值为主
        return Object.values(this.list)
    }
    //? 返回Set中所有元素的键/值对
    entries() {
        // 键和值是相等的，以值为主
        return Object.entries(this.list).map(item => {
            item[0] = item[1]
            return item
        })
    }
    //? 以插入顺序执行给定的回调函数
    forEach(callback) {
        let keys = this.keys()
        for (let i = 0; i < keys.length; i++) {
            callback(keys[i], keys[i], this)
        }
    }
    //? 遍历效果
    *[Symbol.iterator]() {
        for (const item of this.list) {
            yield item;
        }
    }
}
